pub mod trade_bot_with;
pub mod trade_holding_data;
pub mod trade_holding;
pub mod trade_order_data;
pub mod trade_order;
pub mod trade_strategy_data;
pub mod trade_strategy;
pub mod trade_tx_of;
pub mod trade_storder;

pub const TRADE_HOLDING_ID_MONEY_CNY: &str = "MY.HOLDING.MONEY.CNY";
pub const TRADE_HOLDING_ID_MONEY_HKD: &str = "MY.HOLDING.MONEY.HKD";
pub const TRADE_HOLDING_ID_MONEY_USD: &str = "MY.HOLDING.MONEY.USD";

/// An enum representing key values related to the Golden Ratio.
#[derive(Debug, Clone, PartialEq)]
pub enum GoldenRatio {
    Phi0618,
    Phi0382,
    Phi0236,
    Phi0191,
    Phi05,
    Phi1191,
    Phi1236,
    Phi1382,
    Phi15,
    Phi1618,
    Phi2x618,
    Phi4x236,
}

impl GoldenRatio {
    /// Returns the numerical value associated with the enum variant.
    pub fn as_f64(&self) -> f64 {
        match self {
            GoldenRatio::Phi0618 => 0.6180339887498949,
            GoldenRatio::Phi0382 => 1.0 - GoldenRatio::Phi0618.as_f64(),
            GoldenRatio::Phi0236 => 0.23606797749979,
            GoldenRatio::Phi0191 => 0.18541019662496847,
            GoldenRatio::Phi05 => 0.5,
            GoldenRatio::Phi1191 => 1.0 + GoldenRatio::Phi0191.as_f64(),
            GoldenRatio::Phi1236 => 1.0 + GoldenRatio::Phi0236.as_f64(),
            GoldenRatio::Phi1382 => 1.0 + GoldenRatio::Phi0382.as_f64(),
            GoldenRatio::Phi15 => 1.5,
            GoldenRatio::Phi1618 => 1.618033988749895,
            GoldenRatio::Phi2x618 => 2.0 * GoldenRatio::Phi0618.as_f64(), // Direct calculation
            GoldenRatio::Phi4x236 => 4.0 * GoldenRatio::Phi0236.as_f64(), // Direct calculation
        }
    }

    /// 下跌根据黄金分割位置买的份额
    pub fn drop_buy_share(&self) -> u16 {
        match self {
            GoldenRatio::Phi0191 => 1,
            GoldenRatio::Phi0236 => 2,
            GoldenRatio::Phi0382 => 4,
            GoldenRatio::Phi05 => 5,
            GoldenRatio::Phi0618 => 6,
            _ => 1,
        }
    }

    /// Returns the nearest `GoldenRatio` for a given `f64` value.
    pub fn nearest_phi(value: f64) -> Self {
        [
            GoldenRatio::Phi0618,
            GoldenRatio::Phi0382,
            GoldenRatio::Phi0236,
            GoldenRatio::Phi0191,
            GoldenRatio::Phi05,
            GoldenRatio::Phi1191,
            GoldenRatio::Phi1236,
            GoldenRatio::Phi1382,
            GoldenRatio::Phi15,
            GoldenRatio::Phi1618,
            GoldenRatio::Phi2x618,
            GoldenRatio::Phi4x236,
        ]
            .iter()
            .min_by(|&a, &b| {
                let diff_a = (value - a.as_f64()).abs();
                let diff_b = (value - b.as_f64()).abs();
                diff_a.partial_cmp(&diff_b).unwrap_or(std::cmp::Ordering::Equal)
            })
            .cloned()
            .unwrap_or(GoldenRatio::Phi1618)
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[tokio::test]
    async fn test_phi() {
        let phi_0618 = GoldenRatio::Phi0618;
        let phi_0382 = GoldenRatio::Phi0382;
        let phi_0236 = GoldenRatio::Phi0236;
        let phi_0191 = GoldenRatio::Phi0191;
        let phi_05 = GoldenRatio::Phi05;
        let phi_1191 = GoldenRatio::Phi1191;
        let phi_1236 = GoldenRatio::Phi1236;
        let phi_1382 = GoldenRatio::Phi1382;
        let phi_15 = GoldenRatio::Phi15;
        let phi_1618 = GoldenRatio::Phi1618;
        let phi_2618 = GoldenRatio::Phi2x618;
        let phi_4236 = GoldenRatio::Phi4x236;

        println!("  0.618 of Golden Ratio (φ⁻¹): {}", phi_0618.as_f64());
        println!("Φ 0.382: {}", phi_0382.as_f64());
        println!("Φ 0.236: {}", phi_0236.as_f64());
        println!("Φ 0.191: {}", phi_0191.as_f64());
        println!("Φ 0.5: {}", phi_05.as_f64());
        println!("Φ 1.191: {}", phi_1191.as_f64());
        println!("Φ 1.236: {}", phi_1236.as_f64());
        println!("Φ 1.382: {}", phi_1382.as_f64());
        println!("Φ 1.5: {}", phi_15.as_f64());
        println!("Φ 1.618: {}", phi_1618.as_f64());
        println!("Φ 2x.618: {}", phi_2618.as_f64());
        println!("Φ 4x.236: {}", phi_4236.as_f64());
    }

    #[tokio::test]
    async fn test_nearest_phi() {
        // Adjusted expected values based on the actual closest values
        assert_eq!(GoldenRatio::Phi0382, GoldenRatio::nearest_phi(0.382));
        assert_eq!(GoldenRatio::Phi0618, GoldenRatio::nearest_phi(0.618));
        assert_eq!(GoldenRatio::Phi0236, GoldenRatio::nearest_phi(0.236));
        assert_eq!(GoldenRatio::Phi05, GoldenRatio::nearest_phi(0.5));
        assert_eq!(GoldenRatio::Phi2x618, GoldenRatio::nearest_phi(2.0 * 0.618));
        assert_eq!(GoldenRatio::Phi0191, GoldenRatio::nearest_phi(0.191));
        assert_eq!(GoldenRatio::Phi1382, GoldenRatio::nearest_phi(1.382));
        assert_eq!(GoldenRatio::Phi15, GoldenRatio::nearest_phi(1.5));
        assert_eq!(GoldenRatio::Phi1618, GoldenRatio::nearest_phi(1.618));
        assert_eq!(GoldenRatio::Phi4x236, GoldenRatio::nearest_phi(4.0 * 0.236));

        // Additional test cases
        assert_eq!(GoldenRatio::Phi0382, GoldenRatio::nearest_phi(0.36)); // Closer to 0.382 than 0.236
        assert_eq!(GoldenRatio::Phi0382, GoldenRatio::nearest_phi(0.381966011250105));
    }
}
